{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# 我不在的时候，都争成啥样\n",
    "任务要求:\n",
    "\n",
    "(1)我们有个显示器，上面1s显示一次时间信息(咱们用数码管来显示进程已运行的时间)。\n",
    "\n",
    "(2)我有重要信息要给给大家看时，必须显示该信息3s,这期间不能在显示时间了。(按键被按下后，表示重要信息来显示，显示9999)。\n",
    "\n",
    "下面是没加锁的显示，怎么我要求的3s显示我的重要信息，没达到啊?都怪显示时间的进程，抢着要显示，这不这要信息看不见了，都怪他。此时，两个进程还在争..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from multiprocessing import Process\n",
    "import time\n",
    "import os\n",
    "from sakshat import SAKSHAT\n",
    "from sakspins import SAKSPins as PINS\n",
    "\n",
    "#普通１s显示进程进程\n",
    "def dig_normal_one_second(task_name,delay_second):\n",
    "    print(task_name + \"任务启动\")\n",
    "    try:\n",
    "        while True:\n",
    "            #延时等待显示下述信息\n",
    "            time.sleep(delay_second)\n",
    "            \n",
    "            #显示普通信息\n",
    "            SAKS.digital_display.show((\"%04d\" % (1234)))\n",
    "            \n",
    "    except KeyboardInterrupt:\n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "#重要10s显示进程\n",
    "def dig_normal_ten_second(task_name,delay_second):\n",
    "    print(task_name + \"任务启动\")\n",
    "    try:\n",
    "        while True:\n",
    "            #延时等待显示下述信息\n",
    "            time.sleep(delay_second)\n",
    "            \n",
    "            #显示重要重要信息9999显示2秒，６６６６显示2秒\n",
    "            SAKS.digital_display.show((\"%04d\" % (9999)))\n",
    "            time.sleep(2)\n",
    "            SAKS.digital_display.show((\"%04d\" % (6666)))\n",
    "            time.sleep(2)\n",
    "            \n",
    "    except KeyboardInterrupt:\n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "if __name__ == \"__main__\":\n",
    "    try:\n",
    "        #Declare the SAKS Board\n",
    "        SAKS = SAKSHAT()\n",
    "\n",
    "        #创建温度采集、本地显示温度、远程发送温度、本地温度存储进程\n",
    "        one_second_prog = Process(target=dig_normal_one_second, args=(\"普通１s显示进程\", 1))\n",
    "        ten_second_prog = Process(target=dig_normal_ten_second, args=(\"重要10s显示进程\", 10))\n",
    "        \n",
    "        # 启动任务\n",
    "        one_second_prog.start()\n",
    "        ten_second_prog.start()\n",
    "\n",
    "        #等待启动的进程执行结束\n",
    "        one_second_prog.join()\n",
    "        ten_second_prog.start()\n",
    "\n",
    "    except KeyboardInterrupt:\n",
    "        print(\"任务被终止了\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 我来了，都别争了，咱们定个规矩\n",
    "好了，别争了，我来定规矩，我把显示屏锁起来了，这又把钥匙，拿到这把钥匙，打开显示屏锁，显示你的信息，用完显示屏后，把显示屏锁起来，钥匙归还。记得一定要归还钥匙啊。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from multiprocessing import Process, Lock\n",
    "import time\n",
    "import os\n",
    "from sakshat import SAKSHAT\n",
    "from sakspins import SAKSPins as PINS\n",
    "\n",
    "#普通１s显示进程进程\n",
    "def dig_normal_one_second(task_name,delay_second, display_lock):\n",
    "    print(task_name + \"任务启动\")\n",
    "    try:\n",
    "        while True:\n",
    "            #延时等待显示下述信息\n",
    "            time.sleep(delay_second)\n",
    "            \n",
    "            #延时等待显示下述信息\n",
    "            display_lock.acquire()\n",
    "            \n",
    "            #显示普通信息\n",
    "            SAKS.digital_display.show((\"%04d\" % (1234)))\n",
    "            \n",
    "            #释放显示锁\n",
    "            display_lock.release()\n",
    "            \n",
    "    except KeyboardInterrupt:\n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "#重要10s显示进程\n",
    "def dig_normal_ten_second(task_name,delay_second, display_lock):\n",
    "    print(task_name + \"任务启动\")\n",
    "    try:\n",
    "        while True:\n",
    "            #延时等待显示下述信息\n",
    "            time.sleep(delay_second)\n",
    "            \n",
    "            #获取显示锁\n",
    "            display_lock.acquire()\n",
    "            \n",
    "            #显示重要重要信息9999显示2秒，６６６６显示2秒\n",
    "            SAKS.digital_display.show((\"%04d\" % (9999)))\n",
    "            time.sleep(2)\n",
    "            SAKS.digital_display.show((\"%04d\" % (6666)))\n",
    "            time.sleep(2)\n",
    "            \n",
    "            #释放显示锁\n",
    "            display_lock.release()\n",
    "            \n",
    "    except KeyboardInterrupt:\n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "if __name__ == \"__main__\":\n",
    "    try:\n",
    "        #Declare the SAKS Board\n",
    "        SAKS = SAKSHAT()\n",
    "        \n",
    "        disp_lock = Lock()\n",
    "\n",
    "        #创建温度采集、本地显示温度、远程发送温度、本地温度存储进程\n",
    "        one_second_prog = Process(target=dig_normal_one_second, args=(\"普通１s显示进程进程\", 1, disp_lock))\n",
    "        ten_second_prog = Process(target=dig_normal_ten_second, args=(\"重要10s显示进程\", 10, disp_lock))\n",
    "        \n",
    "        # 启动任务\n",
    "        one_second_prog.start()\n",
    "        ten_second_prog.start()\n",
    "\n",
    "        #等待启动的进程执行结束\n",
    "        one_second_prog.join()\n",
    "        ten_second_prog.start()\n",
    "\n",
    "    except KeyboardInterrupt:\n",
    "        print(\"任务被终止了\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# 锁虽好用，使用不当，身受重伤\n",
    "使用锁不当最容易出的两个问题就是:死锁和优先级反转，死锁是最致命的。\n",
    "\n",
    "(1)死锁。什么情况会产生死锁呢，A进程此时手持锁1，在等待锁2;B进程此时手持锁2，在等待锁1;看吧，都在等着对方释放当前手持的锁，对于对峙中(这就叫死锁)。\n",
    "\n",
    "(2)优先级反转。低优先级A进程此时手持锁1，在执行自己的任务;此时高优先级B进程变为运行态，要拿锁1，继续执行;但低优先级A进程未执行完毕，一直持有者锁1，这期间低优先级A进程，被中优先级C、D、E...进程抢了CPU，低优先级A进程一直处于睡眠态，等待这些中优先级任务执行完毕后，才执行自己的任务，待自己的任务执行完后，释放了锁1；此时，被遗忘很久的高优先级B才执行，B很伤心，我这么高的优先级，怎么被拖到现在才执行，都是锁惹的祸。看吧这就叫优先级反转，高优先级的进程被“降到”低优先级运行了。\n",
    "\n",
    "那有结局措施吗？当然有了，措施就是:留待python下篇再讲。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# 稍事休息，继续攀登\n",
    "至此，我们已经掌握了操作系统为我们提供的3大利器——多任务、进程间通信、进程间同步，我们可以按照自己的方式将任务合理的分解为多任务方式实现了，让程序设计变为一种美的设计。\n",
    "\n",
    "下面我们开始玩耍我们NXEZ扩展板了，对于每种外设，介绍每种外设对象提供的方法。依照创客百科中”SAKS SDK 开发文档“进行讲解和实验。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
